home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
amok_lha
/
amok59.lha
/
AmokEd_V1.02b
/
txt
/
EdLowLevel.mod
< prev
next >
Wrap
Text File
|
1993-08-15
|
15KB
|
576 lines
(*************************************************************************
:Program. EdLowLevel.mod
:Contents. Lowlevel-Support-Routines for AmokEd
:Author. Hartmut Goebel
:Language. Oberon
:Translator. AmigaOberon V2.00
:Imports. Printf (Volker Rudolph), SupLib (Hartmut Goebel)
:History. V0.1, 03 Dec 1990 Hartmut Goebel
:History. V1.0, 14 Apr 1991 Hartmut Goebel [hG]
:History. V1.1, 22 Apr 1991 [hG] New/FreeLine über Exec.Alloc/FreeMem
:History. V1.2, 28 Apr 1991 [hG] +TextInit -NewEdit
:History. V1.2b 29 Apr 1991 [hG] ^WindowTitle
:History. V1.2c 29 May 1991 [hG] changed check of Dos-Version
:History. V1.2d 19 Jun 1991 [hG] +neue FreeLines() (Volker Rudolph)
:History. V1.2e 12 Oct 1991 [hG] +NCStrCmp
:History. V1.2f 18 Oct 1991 [hG] +DeletePort
:Date. 19 Oct 1991 03:02:00
*************************************************************************)
(* $Debug- *)
MODULE EdLowLevel;
IMPORT
Printf, (*io,*)
arg: Arguments,
con: Console,
d : Dos,
e : Exec,
eAD: EdApplDefs,
es : ExecSupport,
edE: EdErrors,
edG: EdGlobalVars,
g : Graphics,
I : Intuition,
ie : InputEvent,
lst: EdLists,
ol : OberonLib,
sl : SupLib,
str: Strings,
s : SYSTEM;
VAR
TitleText: edG.StringPtr; (* sicherstellen, daß Titel erhalten bleibt *)
CONST
CTRLC = LONGSET{d.ctrlC};
PROCEDURE MoveToCursor*;
BEGIN
g.Move(edG.RPort,edG.XTBase+(edG.Text.pos-edG.Text.topPos)*edG.XSize,
edG.YTBase+(SHORT(edG.Text.line-edG.Text.topLine))*edG.YSize);
END MoveToCursor;
(*-------------------------------------------------------------------------*)
PROCEDURE Length(str{8}: edG.StringPtr): INTEGER;
VAR
p: edG.StringPtr;
BEGIN
WHILE str[0] # 0X DO
INC(str); END;
RETURN SHORT(s.VAL(LONGINT,str)-s.VAL(LONGINT,p));
END Length;
PROCEDURE CopyString*(from: edG.StringPtr): edG.StringPtr;
VAR
len: INTEGER;
new: edG.StringPtr;
BEGIN
IF from=NIL THEN RETURN NIL; END;
len := str.Length(from^)+1;
ol.New(new,len);
IF new=NIL THEN
INCL(edG.Status,edG.memoryFail); edG.Rc := edE.cmdSevere;
RETURN NIL;
END;
e.CopyMem(from^,new^,len);
RETURN new;
END CopyString;
PROCEDURE FreeString*(string: edG.StringPtr);
BEGIN
DISPOSE(string);
END FreeString;
(* $Debug= *)
PROCEDURE NCStrCmp*(str1{8}, str2{9}: edG.StringPtr): INTEGER;
BEGIN
WHILE CAP(str1[0]) = CAP(str2[0]) DO
IF str1[0] = 0X THEN
RETURN 0; END;
INC(str1); INC(str2);
END;
RETURN ORD(str1[0])-ORD(str2[0]);
END NCStrCmp;
(* $Debug- *)
(*-------------------------------------------------------------------------*)
PROCEDURE IsAscii*(ch{0}: CHAR): BOOLEAN;
BEGIN
CASE ch OF
"0".."9","A".."Z","a".."z","_",CHR(192)..CHR(255): RETURN TRUE;
ELSE
RETURN FALSE;
END;
END IsAscii;
PROCEDURE WordLen*(str{8}: edG.StringPtr): INTEGER;
VAR
i: INTEGER;
BEGIN
i := 0;
WHILE (str[0] # 0X) AND (str[0] # " ") DO
INC(i);
INC(str);
END;
RETURN i;
END WordLen;
PROCEDURE LastNoSpace*(string{8}: edG.StringPtr): INTEGER;
VAR
i: INTEGER;
BEGIN
i := str.Length(string^);
REPEAT
DEC(i);
UNTIL (i = 0) OR (string[i] # " ");
RETURN i;
END LastNoSpace;
PROCEDURE FirstNoSpace*(string{8}: edG.StringPtr): INTEGER;
VAR
i: INTEGER;
BEGIN
i := 0;
WHILE string[i] = " " DO
INC(i);
END;
IF string[i] = "\o" THEN i := 0; END;
RETURN i;
END FirstNoSpace;
PROCEDURE StripEndSpaces*;
VAR
len: INTEGER;
BEGIN
len := str.Length(edG.LineBuffer);
REPEAT
DEC(len);
UNTIL (len < 0) OR (edG.LineBuffer[len] # 20X);
INC(len);
edG.LineBuffer[len] := 0X;
edG.LineBufferLen := len;
END StripEndSpaces;
PROCEDURE FillUpSpaces*;
VAR
j, i: INTEGER;
BEGIN
i := edG.Text.pos;
j := edG.LineBufferLen;
WHILE i > j DO
edG.LineBuffer[j] := 20X;
INC(j);
END;
edG.LineBuffer[j] := 0X;
edG.LineBufferLen := j;
END FillUpSpaces;
(*-------------------------------------------------------------------------*)
PROCEDURE FreeLines*(VAR List: lst.List; Start, End: edG.LinePtr);
VAR
This: edG.LinePtr;
TempList: lst.Mark;
memStart, memEnd:e.ADDRESS;
BEGIN
lst.SetMark(TempList,Start,End);
lst.RemoveMark(List,TempList);
TempList.tail.next := NIL;
This := TempList.head(edG.Line);
memStart := This;
memEnd := This;
REPEAT
TempList.head := This.next; (* gar nicht erst Remove, gleich freigeben *)
WITH This:edG.Line DO
IF memEnd = This THEN
INC(memEnd,edG.LineAllocSize);
ELSE
e.FreeMem(memStart,memEnd-memStart);
memStart := This;
memEnd := s.VAL(LONGINT,This)+edG.LineAllocSize;
END; (* IF *)
IF memEnd = This.string THEN
INC(memEnd,This.len);
ELSE
e.FreeMem(memStart,memEnd-memStart);
memStart := This.string;
memEnd := s.VAL(LONGINT,This.string)+This.len;
END; (* IF *)
END; (* WITH *)
This := TempList.head;
UNTIL This = NIL;
e.FreeMem(memStart,memEnd-memStart);
END FreeLines;
PROCEDURE NewLine*(VAR line: edG.LinePtr; len: INTEGER);
BEGIN
line := e.AllocMem(len+edG.LineAllocSize,LONGSET{});
IF line # NIL THEN
(* $TypeChk- *)
WITH line:edG.Line DO
s.INIT(line);
line.string := s.VAL(LONGINT,line)+edG.LineAllocSize;
line.string^ := "";
line.len := len;
END; (* WITH *)
(* $TypeChk= *)
RETURN;
END;
INCL(edG.Status,edG.memoryFail);
END NewLine;
PROCEDURE CreateLineCopy*(from: edG.LinePtr): edG.LinePtr;
VAR
NewOne: edG.LinePtr;
BEGIN
NewOne := e.AllocMem(from(edG.Line).len+edG.LineAllocSize,LONGSET{});
IF NewOne#NIL THEN
(* $TypeChk- *)
WITH NewOne:edG.Line DO
s.INIT(NewOne);
NewOne.len := from(edG.Line).len;
NewOne.string := s.VAL(LONGINT,NewOne)+edG.LineAllocSize;
e.CopyMemQuick(from(edG.Line).string^,NewOne.string^,NewOne.len);
END; (* WITH *)
(* $TypeChk= *)
RETURN NewOne;
END;
INCL(edG.Status,edG.memoryFail);
RETURN NIL;
END CreateLineCopy;
(*-------------------------------------------------------------------------*)
PROCEDURE StrToInt*(string: edG.StringPtr; VAR int: LONGINT): BOOLEAN;
VAR
n: INTEGER;
neg: BOOLEAN;
BEGIN
int := 0; neg := FALSE;
WHILE string[0]=20X DO INC(string) END;
CASE string[0] OF "-","+": neg := string[0]="-"; INC(string) ELSE END;
LOOP
CASE string[0] OF "0".."9":
n := ORD(string[0])-ORD("0");
IF int>(MAX(LONGINT)-n) DIV 10 THEN RETURN FALSE
ELSE int := 10*int + n END |
ELSE
IF neg THEN int := -int END;
WHILE string[0]=20X DO INC(string) END;
RETURN string[0]=0X
END;
INC(string);
END;
END StrToInt;
(*-------------------------------------------------------------------------*)
PROCEDURE KillMarks;
VAR
i, j: INTEGER;
BEGIN
i := edG.NumPingPongs;
REPEAT (* remove PingPong Marks *)
DEC(i);
IF edG.PingPong[i].txt = edG.Text THEN edG.PingPong[i].txt := NIL; END;
UNTIL i = 0;
j := 0; (*i:=0*)
REPEAT (* remove Block Marks *)
IF edG.BStack[i].Owner # edG.Text THEN
edG.BStack[j].Owner := edG.BStack[i].Owner;
INC(j);
END;
INC(i);
UNTIL i >= edG.BStackCurrDepth; (* >= wg. BStackCurrDepth = 0 *)
edG.BStackCurrDepth := j;
IF edG.Block.Owner = edG.Text THEN (* unblock *)
edG.Block.SNum := -1; edG.Block.ENum := -1; END;
END KillMarks;
PROCEDURE TextInit*(VAR nw: I.NewWindow): edG.TextHeaderPtr;
VAR
txt: edG.TextHeaderPtr;
BEGIN
(* es ist unnötig, Felder mit NIL oder 0 zu initialisieren,
* da ol.New mit {e.memClear} alloziert
*)
ol.New(txt,s.SIZE(edG.TextHeader));
IF txt # NIL THEN (* $TypeChk- *)
s.INIT(txt); (* $TypeChk= *)
txt.name := edG.unNamed;
txt.propGadget := edG.Gadget1;
txt.propGadget.specialInfo := s.ADR(txt.propInfo);
txt.propInfo := edG.Gadget1SInfo;
nw.firstGadget := s.ADR(txt.propGadget);
txt.window := sl.OpenPortWindow(nw,edG.MainPort);
IF txt.window = NIL THEN
DISPOSE(txt); RETURN NIL;
END;
I.SetWindowTitles(txt.window,s.ADR(edG.Copyright),-1);
txt.numberOfLines := 1;
NewLine(txt.actLinePtr,edG.ChunkSize);
lst.AddHead(txt.lineList,txt.actLinePtr);
txt.topLinePtr := txt.actLinePtr;
txt.iconTop := 12;
txt.margin := 69;
lst.AddTail(edG.EditList,txt);
IF edG.Text#NIL THEN (* nicht erster Text *)
txt.dirLock := d.DupLock(edG.Text.dirLock);
txt.status := edG.Text.status - LONGSET{edG.quit,edG.macroWithQuit,
edG.keepTitle,edG.modified};
txt.tabStop := edG.Text.tabStop;
IF edG.Text.font#NIL THEN
txt.font := edG.Text.font;
INC(txt.font.accessors);
g.SetFont(txt.window.rPort,txt.font);
END;
ELSE
edG.Text := txt;
txt.dirLock := d.DupLock(arg.Me.currentDir);
txt.tabStop := 4;
txt.status := LONGSET{edG.insertMode};
END;
END;
RETURN txt;
END TextInit;
PROCEDURE EndEdit*;
BEGIN
IF edG.Text.lineList.head#NIL THEN
FreeLines(edG.Text.lineList,edG.Text.lineList.head(edG.Line),
edG.Text.lineList.tail(edG.Line));
END;
IF edG.Text.font#NIL THEN
g.SetFont(edG.RPort,edG.Text.window.wScreen.rastPort.font);
g.CloseFont(edG.Text.font);
END;
IF edG.Text.window # NIL THEN sl.CloseWindowSafely(edG.Text.window); END;
KillMarks;
d.UnLock(edG.Text.dirLock);
lst.Remove(edG.EditList,edG.Text);
DISPOSE(edG.Text);
edG.Text := edG.EditList.head(edG.TextHeader);
END EndEdit;
(*-------------------------------------------------------------------------*)
PROCEDURE Title*(winText{8}: ARRAY OF CHAR); (* $CopyArrays- *)
BEGIN
I.SetWindowTitles(edG.Text.window,s.ADR(winText),-1);
END Title;
PROCEDURE doTitle*;
BEGIN
DISPOSE(TitleText);
TitleText := CopyString(edG.Arg[0]);
I.SetWindowTitles(edG.Text.window,TitleText,-1);
INCL(edG.Text.status,edG.keepTitle); edG.Rc := edE.cmdValid2;
END doTitle;
(*
* zeigt edG.Text.actLineNum, edG.Text.numberOfLines, edG.Text.pos,
* edG.Text.Name und ggf. Statusmeldungen an.
*)
PROCEDURE WindowTitle*;
CONST
Modified = "(modified)\o";
VAR
Win: I.WindowPtr;
len, maxlen: INTEGER;
font, oldfont: g.TextFontPtr;
mod: ARRAY 11 OF CHAR;
BEGIN
IF edG.memoryFail IN edG.Status THEN
I.SetWindowTitles(edG.Text.window,s.ADR(edG.NoMemory),-1);
RETURN;
END;
IF (edG.Rc > edE.TitleThreshhold) THEN RETURN; END;
IF edG.modified IN edG.Text.status THEN
e.CopyMem(Modified,mod,11);
ELSE
e.CopyMem(edG.Spaces,mod,11);
END;
Printf.SPrintf5(edG.Text.wTitle,"%3ld/%-3ld %3ld %s %s ",
edG.Text.line+1,edG.Text.numberOfLines,edG.Text.pos+1,
s.ADR(edG.Text.name),s.ADR(mod));
Win := edG.Text.window;
oldfont := Win.rPort.font;
g.SetFont(Win.rPort,Win.wScreen.rastPort.font);
IF edG.kick20 IN edG.Status THEN
I.SetWindowTitles(Win,s.ADR(edG.Text.wTitle),-1);
ELSE
len := str.Length(edG.Text.wTitle);
Win.title := s.ADR(edG.Text.wTitle);
font := Win.rPort.font;
maxlen := (Win.width-90) DIV font.xSize;
IF maxlen < 0 THEN maxlen := 0; END;
IF len > maxlen THEN len := maxlen; END;
g.SetAPen(Win.rPort,0); g.SetBPen(Win.rPort,1);
g.Move(Win.rPort,30,font.baseline+1);
g.Text(Win.rPort,edG.Text.wTitle,len); (* No flash *)
g.SetAPen(Win.rPort,1); g.SetBPen(Win.rPort,0);
IF maxlen - len > 0 THEN
g.RectFill(Win.rPort,Win.rPort.x,1,Win.width-54,font.ySize+1);
END;
END;
g.SetFont(Win.rPort,oldfont);
END WindowTitle;
(*-------------------------------------------------------------------------*)
(*
* Check break by scanning pending messages in the I stream for a ^C.
* msgCheck forces a check, else the check is only made if the signal is
* set in the I stream (the signal is reset).
*)
(* $Debug= *)
PROCEDURE BreakCheck*(): BOOLEAN;
VAR
im: I.IntuiMessagePtr;
class: LONGSET;
qual: SET;
code: INTEGER;
BEGIN
IF (edG.msgCheck IN edG.Status)
OR (edG.MainPort.sigBit IN e.SetSignal(LONGSET{},LONGSET{})) THEN
EXCL(edG.Status,edG.msgCheck);
s.SETREG(0,e.SetSignal(LONGSET{},
LONGSET{edG.MainPort.sigBit})); (* Löschen *)
e.Forbid();
im := edG.MainPort.msgList.head;
WHILE im.execMessage.node.succ # NIL DO
class := im.class; qual := im.qualifier-{ie.capsLock,8..15};
code := im.code;
IF (im.idcmpWindow = edG.Text.window)
AND (im.class = LONGSET{I.rawKey}) (* is IDCMPFlag, not ie.Class *)
AND ({ie.control} = im.qualifier-{ie.capsLock,8..15})
(* only check Qualifier-Keys (lower 8 Bits) *)
AND (im.code = s.VAL(SHORTINT,edG.CtrlC)) THEN
e.Permit();
(*
io.WriteInt(s.VAL(LONGINT,class),5);
io.WriteInt(s.VAL(INTEGER,qual),5);
io.WriteInt(s.VAL(INTEGER,code),5);io.WriteLn;
io.Write("+");
*)
s.SETREG(0,e.SetSignal(CTRLC,CTRLC)); (* setzen *)
RETURN TRUE;
END;
im := im.execMessage.node.succ;
END;
e.Permit();
(*
io.WriteInt(s.VAL(LONGINT,class),5);
io.WriteInt(s.VAL(INTEGER,qual),5);
io.WriteInt(s.VAL(INTEGER,code),5);io.WriteLn;
*)
END;
(*io.Write("-");*)
RETURN FALSE;
END BreakCheck;
(* $Debug- *)
PROCEDURE BreakReset*;
BEGIN;
s.SETREG(0,e.SetSignal(LONGSET{},CTRLC));
END BreakReset;
(*-------------------------------------------------------------------------*)
(* Sucht <txt>, zu dem <win> gehört *)
PROCEDURE FindEdit*(win{8}: I.WindowPtr): edG.TextHeaderPtr;
VAR
txt: edG.TextHeaderPtr;
BEGIN
IF win = NIL THEN RETURN NIL; END;
txt := edG.EditList.head(edG.TextHeader);
WHILE txt # NIL DO
IF txt.window = win THEN RETURN txt; END;
txt := txt.node.next(edG.TextHeader);
END;
RETURN NIL;
END FindEdit;
(*-------------------------------------------------------------------------*)
PROCEDURE DeletePort*(port: e.MsgPortPtr);
VAR
n, s: e.MessagePtr;
BEGIN
e.Forbid();
n := port.msgList.head;
WHILE n.node.succ # NIL DO
s := n.node.succ;
IF n.replyPort # port THEN (* Message does not belong to us *)
e.Remove(n);
e.ReplyMsg(n);
END;
n := s;
END;
e.Permit;
es.DeletePort(port);
END DeletePort;
(*-------------------------------------------------------------------------*)
BEGIN
(*
edG.Text := NIL;
lst.Init(edG.EditList);
edG.LineBuffer := ""; edG.LineBufferLen := 0;
*)
edG.MainPort := es.CreatePort("",0);
IF edG.MainPort = NIL THEN HALT(20); END;
edG.MainReq := es.CreateExtIO(edG.MainPort,s.SIZE(e.IOStdReq));
IF edG.MainReq = NIL THEN HALT(20); END;
s.SETREG(0,e.OpenDevice(con.consoleName,-1,edG.MainReq,LONGSET{}));
con.base := edG.MainReq.device;
IF d.dos.lib.version>=36 THEN INCL(edG.Status,edG.kick20);
ELSE EXCL(edG.Status,edG.kick20);
END;
CLOSE
WHILE edG.EditList.head#NIL DO (* falls noch was offen ist *)
EndEdit; END;
IF edG.DelLinePtr # NIL THEN
e.FreeMem(edG.DelLinePtr(edG.Line).string,edG.DelLinePtr(edG.Line).len);
e.FreeMem(edG.DelLinePtr,edG.LineAllocSize);
END;
IF con.base # NIL THEN e.CloseDevice(edG.MainReq); END;
IF edG.MainReq # NIL THEN es.DeleteExtIO(edG.MainReq); END;
IF edG.MainPort # NIL THEN es.DeletePort(edG.MainPort); END;
END EdLowLevel.